<template>
  <div class="zui-month">
    <div v-if="showYear" class="year-wrap">
      <div class="left btn-wrap">
        <zui-button circle type="secondary" size="small" :disabled="!canPrevYearClick" @click="onPrevYearClick"
          ><i class="icon-left iconfont-zui icon-zui-arrow-left"></i
        ></zui-button>
      </div>
      <span class="year">{{ curYear }}年</span>

      <div class="right btn-wrap">
        <zui-button circle type="secondary" :disabled="!canNextYearClick" size="small" @click="onNextYearClick"
          ><i class="icon-right iconfont-zui icon-zui-arrow-right"></i
        ></zui-button>
      </div>
    </div>
    <ul class="month-wrap">
      <li
        class="month"
        :class="{ active: isCurMonth(month), disabled: !allowExceed && exceeded(month) }"
        v-for="month in 12"
        :key="month"
        @click="onMonthClick(month, $event)"
        ref="monthRefs"
      >
        {{ month }}{{ !isCurMonth(month) ? '月' : '' }}
      </li>
    </ul>
  </div>
</template>
<script setup>
import { computed, nextTick, onMounted, ref, watch } from 'vue'
import dateUtils from '@nmgolden/date-utils'

const emit = defineEmits(['update:modelValue', 'yearChange', 'monthChange'])

const props = defineProps({
  modelValue: { type: Date, default: () => new Date() },
  maxDate: {
    type: Date,
    default: dateUtils.getFirstDateOfMonth(dateUtils.getToday())
  },
  minDate: {
    type: Date,
    default: new Date(2021, 0, 1)
  },
  showYear: { type: Boolean, default: true },
  allowExceed: Boolean
})

const curDate = ref(props.modelValue)
const monthRefs = ref()
const curYear = computed(() => {
  if (!curDate.value) {
    return
  }
  return curDate.value.getFullYear()
})

const curMonth = computed(() => {
  if (!curDate.value) {
    return
  }
  return curDate.value.getMonth() + 1
})

const canPrevYearClick = computed(() => {
  return curYear.value > props.minDate.getFullYear()
})

const canNextYearClick = computed(() => {
  return curYear.value < props.maxDate.getFullYear()
})

watch(
  () => props.modelValue,
  (value) => {
    curDate.value = value
  }
)
watch(curDate, (value) => {
  emit('update:modelValue', value)
})
watch(curYear, (value, old) => {
  emit('yearChange', value)
})
watch(curMonth, (val, old) => {
  emit('monthChange', val)
  nextTick(() => {
    monthRefs.value[val - 1].scrollIntoView()
  })
})

onMounted(() => {
  curDate.value = props.modelValue
})

// 初始化
if (!curDate.value) {
  curDate.value = dateUtils.getFirstDateOfMonth(dateUtils.getToday())
}

function isCurMonth(month) {
  if (!curDate.value) {
    return false
  }
  return month - 1 == curDate.value.getMonth()
}

function exceeded(month) {
  const exceedMax =
    curYear.value > props.maxDate.getFullYear() ||
    (curYear.value == props.maxDate.getFullYear() && month - 1 > props.maxDate.getMonth())
  const exceedMin =
    curYear.value < props.minDate.getFullYear() ||
    (curYear.value == props.minDate.getFullYear() && month - 1 < props.minDate.getMonth())
  return exceedMax || exceedMin
}

function onMonthClick(month) {
  if (!props.allowExceed && exceeded(month)) {
    return
  }
  const newDate = new Date(Date.UTC(curYear.value, month - 1, 1))
  curDate.value = newDate
}
function onPrevYearClick() {
  const newDate = new Date(Date.UTC(curYear.value - 1, 0, 1))
  curDate.value = newDate
}
function onNextYearClick() {
  const newDate = new Date(Date.UTC(curYear.value + 1, 0, 1))
  curDate.value = newDate
}
</script>
<style lang="scss">
.zui-month {
  .year-wrap {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding-bottom: 16px;
    .btn-wrap {
      .iconfont-zui {
        font-size: var(--zui-size-text-small);
        line-height: 28px;
      }
    }
  }
  .month-wrap {
    width: 100%;
    overflow: auto;
    white-space: nowrap;
    padding-bottom: 16px;
    padding-right: 20px;
    box-sizing: border-box;
    .month {
      display: inline-block;
      width: 28px;
      height: 28px;
      line-height: 28px;
      text-align: center;
      &:not(:first-child) {
        margin-left: 20px;
      }
      &.active {
        background: var(--zui-color-primary);
        border-radius: 16px;
        color: #ffffff;
      }
      &.disabled {
        color: var(--zui-color-text-placeholder);
      }
    }
  }
}
</style>
